<?php
declare(strict_types=1);

namespace App\Controller\Admin;

use App\Annotation\ModuleAndAction;
use App\Helper\CaptchaHelper;
use App\Helper\CookieHelper;
use App\Helper\FileHelper;
use App\Helper\JwtHelper;
use App\Helper\RequestHelper;
use App\Middleware\AdminMiddleware;
use App\Model\AdminRole;
use App\Model\AdminUser;
use Carbon\Carbon;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\Utils\Str;
use Psr\Http\Message\ResponseInterface;
use stdClass;

/**
 * @AutoController()
 * @ModuleAndAction(module="管理后台:管理员:用户管理", icon="fa fa-user")
 * @Middleware(AdminMiddleware::class)
 */
class UserController extends BaseController
{
    /**
     * @var string $model
     */
    public $model = AdminUser::class;

    /**
     * 用户登录
     */
    public function login(): ResponseInterface
    {
        $name = $this->request->post('name', '');
        $password = $this->request->post('password', '');
        $captcha = $this->request->post('captcha', '');
        $response = $this->response->withCookie(CookieHelper::genEmpty(CaptchaHelper::ADMIN_COOKIE_NAME));
        if (empty($name) || empty($password) || empty($captcha)) {
            return $response->json(self::genErrorData('输入内容不能为空！'));
        }
        $cookie = [];
        parse_str($this->request->cookie(CaptchaHelper::ADMIN_COOKIE_NAME, ''), $cookie);
        if (!$cookie) {
            return $response->json(self::genErrorData('请求Header错误！'));
        }
        $ip = RequestHelper::getClientIp($this->request);
        $time = intval($cookie['time'] ?? 0);
        $sign = strval($cookie['sign'] ?? '');
        if (!CaptchaHelper::check($captcha, $ip, $time, $sign, 'business')) {
            return $response->json(self::genErrorData('验证码错误！'));
        }
        /* @var AdminUser $userModel */
        $userModel = AdminUser::query()->where('name', '=', $name)->first();
        if (!$userModel) {
            return $response->json(self::genErrorData('账号错误！'));
        }
        if (sha1($userModel->password_salt . $password) != $userModel->password) {
            return $response->json(self::genErrorData('密码错误！'));
        }
        $lastIp = ($userModel->last_ip ?: $ip);
        $lastLogin = ($userModel->last_login ? $userModel->last_login->toDateTimeString() : Carbon::now()->toDateTimeString());
        $userModel->last_login = Carbon::now();
        $userModel->last_ip = $ip;
        $userModel->save();
        $jwtData = [
            'id' => $userModel->id,
            'name' => $userModel->name,
            'last_ip' => $lastIp,
            'last_login' => $lastLogin,
        ];
        $jwtCookie = CookieHelper::genOne(JwtHelper::ADMIN_JWT_TOKEN, JwtHelper::encode($jwtData), 864000);
        return $response->withCookie($jwtCookie)->json(self::genSuccessData($jwtData));
    }

    /**
     * 取登录用户的信息
     */
    public function getCurrent(): ResponseInterface
    {
        $userInfo = JwtHelper::decodeWithRequest(JwtHelper::ADMIN_JWT_TOKEN, $this->request);
        if (!$userInfo || !$userInfo->data) {
            return $this->response->json(self::genErrorData());
        }
        $more = $this->request->query('more', 0);
        $more = intval($more);
        if ($more <= 0) {
            return $this->response->json(self::genSuccessData($userInfo->data));
        }
        $userModel = AdminUser::find($userInfo->data->id);
        if (!$userModel) {
            return $this->response->json(self::genErrorData());
        }
        $userModel->last_ip = $userInfo->data->last_ip;
        $userModel->last_login = $userInfo->data->last_login;
        return $this->response->json(self::genSuccessData($userModel));
    }

    /**
     * 修改密码
     */
    public function password(): ResponseInterface
    {
        $userInfo = JwtHelper::decodeWithRequest(JwtHelper::ADMIN_JWT_TOKEN, $this->request);
        if (!$userInfo || !$userInfo->data) {
            return $this->response->json(self::genErrorData('请登录！'));
        }
        $old = trim($this->request->post('old', ''));
        $new = trim($this->request->post('new', ''));
        if (empty($old) || empty($new) || !AdminUser::passwordVerify($new)) {
            return $this->response->json(self::genErrorData('请按要求输入！'));
        }
        $userModel = AdminUser::find($userInfo->data->id);
        if (!$userModel) {
            return $this->response->json(self::genErrorData('账号不可用，请确认！'));
        }
        if (sha1($userModel->password_salt . $old) != $userModel->password) {
            return $this->response->json(self::genErrorData('旧密码错误！'));
        }
        $userModel->password_salt = Str::random(8);
        $userModel->password = sha1($userModel->password_salt . $new);
        if ($userModel->save()) {
            return $this->logout('密码修改成功，请使用新密码重新登录！');
        }
        return $this->response->json(self::genErrorData('系统错误，密码修改失败！'));
    }

    /**
     * 退出登录
     * @param string $msg
     * @return ResponseInterface
     */
    public function logout(string $msg = 'ok'): ResponseInterface
    {
        return $this->response
            ->withCookie(CookieHelper::genEmpty(JwtHelper::ADMIN_JWT_TOKEN))
            ->json(self::genSuccessData($msg));
    }

    /**
     * 更新个人基本资料
     */
    public function me(): ResponseInterface
    {
        $userInfo = JwtHelper::decodeWithRequest(JwtHelper::ADMIN_JWT_TOKEN, $this->request);
        if (!$userInfo || !$userInfo->data) {
            return $this->response->json(self::genErrorData('请登录！'));
        }
        $userModel = AdminUser::find($userInfo->data->id);
        if (!$userModel) {
            return $this->response->json(self::genErrorData('账号不可用，请确认！'));
        }
        $post = $this->request->post();
        $imagePath = $post['image_path'] ?? '';
        $imagePathOld = $userModel->image_path;
        $changed = false;
        if ($imagePath != $imagePathOld && !empty($imagePath)) {
            FileHelper::del(
                PageController::ADMIN_UPLOAD_IMAGE_ROOT_PATH . '/' . $imagePathOld,
                PageController::ADMIN_UPLOAD_IMAGE_ROOT_PATH
            );
            $userModel->image_path = $imagePath;
            $changed = true;
        }
        $keys = ['about_me', 'address', 'email', 'phone', 'sex'];
        foreach ($keys as $key) {
            $postVal = $post[$key] ?? null;
            if ($postVal != $userModel->{$key}) {
                $userModel->{$key} = $postVal;
                $changed = true;
            }
        }
        if ($changed && $userModel->save()) {
            return $this->response->json(self::genSuccessData());
        }
        return $this->response->json(self::genErrorData());
    }

    /**
     * 处理添加或修改时，POST的数据（CURD中调用）
     * @param array|null $data
     * @return array|null
     */
    protected function fixPostData(?array $data): ?array
    {
        if (!$data) {
            return null;
        }
        $id = intval($data['id'] ?? 0);
        $password = strval($data['password'] ?? '');
        if ($id <= 0) {
            if (empty($password)) {
                $password = 'abc123';
            }
            $data['password_salt'] = Str::random(8);
            $data['password'] = sha1($data['password_salt'] . $password);
        } else {
            if (empty($password)) {
                unset($data['password'], $data['password_salt']);
            } else {
                $data['password_salt'] = Str::random(8);
                $data['password'] = sha1($data['password_salt'] . $password);
            }
            $imagePath = $data['image_path'] ?? '';
            $imagePathOld = $data['image_path_old'] ?? '';
            if ($imagePath == $imagePathOld) {
                unset($data['image_path']);
            } else {
                FileHelper::del(
                    PageController::ADMIN_UPLOAD_IMAGE_ROOT_PATH . '/' . $imagePathOld,
                    PageController::ADMIN_UPLOAD_IMAGE_ROOT_PATH
                );
            }
        }
        unset($data['image_path_old']);
        return $data;
    }

    /**
     * 处理列表页返回的数据（CURD中调用）
     * @param array|null $data
     * @return array|null
     */
    protected function fixListData(?array $data): ?array
    {
        $adminRoles = AdminRole::all();
        $roleNameById = [];
        foreach ($adminRoles as $adminRole) {
            $roleNameById[$adminRole->id] = $adminRole->name;
        }
        /* @var stdClass $item */
        foreach ($data as $i => $item) {
            $data[$i]->admin_role = ($roleNameById[$item->admin_role_id] ?? '');
            $data[$i]->image_path = AdminUser::getImageUrl($item->image_path, true);
            $data[$i]->sex = AdminUser::SEX_NAMES[$item->sex] ?? '未知';
            unset($data[$i]->password, $data[$i]->password_salt);
        }
        return $data;
    }

    /**
     * 处理详情页返回的数据（CURD中调用）
     * @param stdClass|null $data
     * @return stdClass|null
     */
    protected function fixInfoData(?stdClass $data): ?stdClass
    {
        if (!$data) {
            return null;
        }
        $data->password = '';
        $data->password_salt = '';
        $data->image_url = AdminUser::getImageUrl($data->image_path);
        return $data;
    }
}
